package org.xx.armory.swing.builders;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xx.armory.commons.SysUtils;
import org.xx.armory.commons.Version;
import org.xx.armory.swing.ResourceLoader;
import org.xx.armory.swing.StandardUIController;
import org.xx.armory.swing.UIControllers;

import javax.swing.*;
import java.awt.Image;
import java.util.HashMap;
import java.util.Map;

import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.Validators.notBlank;

/**
 * 预定义的界面模型控制器。用来生成预定义的界面模型元素，比如预定义的Action。
 */
public class StandardUIModelController
        implements StandardUIController {
    private static final String VERSION_NAME = "version";
    private final Logger logger = LoggerFactory.getLogger(StandardUIModelController.class);
    private final Map<String, String> messages;
    private final Map<String, SimpleAction> actions;
    private final Map<String, Image> images;

    public StandardUIModelController(
            String name
    ) {
        this.messages = new HashMap<>();
        this.actions = new HashMap<>();
        this.images = new HashMap<>();

        final UIModel uiModel = UIModelLoader.load(notBlank(name, "name").trim());
        loadFromUIModel(uiModel);
    }

    protected void loadFromUIModel(
            UIModel uiModel
    ) {
        createMessages(uiModel);
        createActions(uiModel);
        createImages(uiModel);
    }

    /**
     * 根据用户界面模型创建创建消息字面量。
     *
     * @param uiModel
     *         关联的UI模型。
     */
    private void createMessages(
            UIModel uiModel
    ) {
        this.messages.putAll(uiModel.getMessages());
    }

    /**
     * 根据用户界面模型创建Action。包括{@link UIModel}中定义的Action和预定义的标准Action。
     *
     * @param uiModel
     *         用户界面模型。
     */
    protected void createActions(
            UIModel uiModel
    ) {
        for (final String actionName : uiModel.getStandardActions()) {
            logger.trace("create standard action[name={}]", actionName);
            this.actions.putIfAbsent(actionName,
                                     UIControllers.STANDARD.getAction(actionName));
        }

        for (final ActionModel model : uiModel.getActions()) {
            logger.trace("create action[name={},title={},enabled={},small-icon={}]", model.getName(), model.getTitle(), model.isEnabled(), model.getSmallIcon());
            final Image smallIconImage = loadImage(uiModel.getResourceName(), model.getSmallIcon());
            final SimpleAction action = new SimpleAction(model.getTitle(),
                                                         model.getMnemonic(),
                                                         model.getAccelerator(),
                                                         smallIconImage != null ? new ImageIcon(smallIconImage) : null,
                                                         model.getDescription(),
                                                         model.getCommand(),
                                                         model.isCauseVerification());
            action.setEnabled(model.isEnabled());
            this.actions.putIfAbsent(model.getName(), action);
        }
    }

    /**
     * 根据用户界面模型创建图像。
     *
     * @param uiModel
     *         用户界面模型。
     */
    protected void createImages(
            UIModel uiModel
    ) {
        for (final ImageModel model : uiModel.getImages()) {
            final Image image = loadImage(uiModel.getResourceName(), model.getSrc());
            if (image == null) {
                throw new IllegalArgumentException("cannot find image: " + model.getSrc());
            }

            this.images.putIfAbsent(model.getName(), image);
        }
    }


//    public SimpleAction getAction(
//            String actionName
//    ) {
//        final String actionName_ = notBlank(actionName, "actionName").trim();
//
//        return uiModel.getActions().stream()
//                      .filter(model -> stringEquals(actionName_, model.getName()))
//                      .map(model -> {
//                          final Image smallIconImage = loadImage(this.uiModel.getResourceName(), model.getSmallIcon());
//                          return new SimpleAction(model.getTitle(),
//                                                  model.getMnemonic(),
//                                                  model.getAccelerator(),
//                                                  smallIconImage != null ? new ImageIcon(smallIconImage) : null,
//                                                  model.getDescription(),
//                                                  model.getCommand(),
//                                                  model.isCauseVerification());
//                      }).findAny()
//                      .orElseThrow(() -> new IllegalArgumentException("cannot find standard-action: " + actionName_));
//    }
//
//    /**
//     * {@inheritDoc}
//     */
//    @Override
//    public Image getImage(
//            String imageName
//    ) {
//        final String imageName_ = notBlank(imageName, "imageName").trim();
//
//        return uiModel.getImages().stream()
//                      .filter(model -> stringEquals(imageName_, model.getName()))
//                      .map(model -> loadImage(this.uiModel.getResourceName(), model.getSrc()))
//                      .filter(Objects::nonNull)
//                      .findAny()
//                      .orElseThrow(() -> new IllegalArgumentException("cannot find standard-image: " + imageName_));
//    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Version getVersion() {
        final String f = this.messages.get(VERSION_NAME);
        if (f == null) {
            return null;
        } else if (f.isEmpty()) {
            return null;
        } else {
            return new Version(f);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final SimpleAction getAction(
            String name
    ) {
        final SimpleAction result = this.actions.getOrDefault(name, null);
        if (result != null) {
            return new SimpleAction(result);
        } else {
            return null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Image getImage(
            String name
    ) {
        return this.images.getOrDefault(name, null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getMessage(
            String name
    ) {
        name = notBlank(name, "name").trim();

        final String f = this.messages.get(name);
        if (f == null) {
            return "${" + name + "}";
        } else if (f.isEmpty()) {
            return "";
        } else {
            return f;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String formatMessage(
            String name,
            Object... values
    ) {
        name = notBlank(name, "name").trim();

        final String f = this.messages.get(name);
        if (f == null) {
            return "${" + name + "}";
        } else if (f.isEmpty()) {
            return "";
        } else {
            return SysUtils.format(f, values);
        }
    }

    /**
     * 从界面模型中加载图片。
     *
     * @param resourceName
     *         加载界面模型的资源名字。
     * @param src
     *         图片名。
     * @return 已加载的图片，如果参数{@code src}是{@code null}或者只包含空白字符则返回{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code lineInfo}是{@code null}。
     */
    protected Image loadImage(
            String resourceName,
            String src
    ) {
        src = trimToEmpty(src);

        if (src.isEmpty()) {
            return null;
        }

        return ResourceLoader.getInstance().loadImage(resourceName, src);
    }
}
